#include"decodethread.h"

DecodeThread::DecodeThread(AVPacketQueue* packet_queue, AVPacketQueue* frame_queue){
    this->packet_queue = packet_queue;
    this->frame_queue = frame_queue;
}

DecodeThread::~DecodeThread(){
    if(mythread){
        Stop();
    }
    if(codec_ctx){
        avcodec_close(codec_ctx);
    }
}

int DecodeThread::Init(AVCodecParameters* par){
    if(!par){
        return -1;
    }
    codec_ctx = avcodec_alloc_context3(nullptr);

    int ret = avcodec_parameters_to_context(codec_ctx, par);
    if(ret < 0){
        return -1;
    }

    AVCodec* codec;
    if(AV_CODEC_ID_H264 == codec_ctx->codec_id){
        codec = avcodec_find_decoder_by_name("h264_qsv");
    }else {
        codec = avcodec_find_decoder(codec_ctx->codec_id);
    }
    if(!codec){
        return -1;
    }

    ret = avcodec_open2(codec_ctx, codec, nullptr);
    if(ret < 0){
        return -1;
    }
    return 0;
}

int DecodeThread::Start(){
    mythread = new thread(&Run, this);
    if(!mythread){
        return -1;
    }
    return 0;
}

int DecodeThread::Stop(){
    Thread::Stop();
}

void DecodeThread::Run(){
    AVFrame* frame = av_frame_alloc();
    while (abort != 1)
    {
        if(frame_queue->Size() > 10){
            this_thread::sleep_for(chrono::milliseconds(10));
            continue;
        }
        AVPacket* pack = packet_queue->Pop(10);
        if(pack){
            int ret = avcodec_send_packet(codec_ctx, pack);
            av_packet_free(&pack);
            if(ret < 0){
                break;
            }

            while (true) {
                ret = avcodec_receive_frame(codec_ctx, frame);
                if(ret == 0){
                    frame_queue->Push(frame);
                    continue;
                }else if (AVERROR(EAGAIN) == ret) {
                    break;
                }else {
                    abort = 1;
                    break;
                }
            }
            
        }else {
            perror("not got packet");
        }
    }
    
}